/*******************************************************************************
 * @file    CommunicationDevice.cpp
 * @brief   USART2通信设备驱动实现（DMA模式）
 *
 * @section 硬件配置
 * - 通信接口：USART2 (PA2-TX/PA3-RX)
 * - DMA通道：
 *   - TX: DMA1_Channel7
 *   - RX: DMA1_Channel6
 * - 缓冲区：
 *   - 发送缓冲区：uart2_dma_tx_buffer[256]
 *   - 接收缓冲区：uart2_dma_rx_buffer[256]
 *
 *
 * @section 关键参数
 * - 波特率：115200bps
 * - 数据格式：8N1
 * - 中断优先级：Preemption=1/Sub=1
 * - DMA优先级：Low
 *
 * @author 飞鸟
 * @version V1.0
 * @date 2025-05-24
 *
 ******************************************************************************/

#include "CommunicationDevice.h"

char uart2_dma_rx_buffer[DMA_RX_BUFFER_SIZE];
char uart2_dma_tx_buffer[DMA_TX_BUFFER_SIZE];


static UART_Device_Typedef config = {
        .UARTx = USART2,
        .port = GPIOA,
        .tx_pin = GPIO_Pin_2,
        .rx_pin = GPIO_Pin_3,
        .gpio_tx_pin_mode = GPIO_Mode_AF_PP,
        .gpio_rx_pin_mode = GPIO_Mode_IN_FLOATING,

        .BaudRate = 115200,
        .WordLength = USART_WordLength_8b,
        .StopBits = USART_StopBits_1,
        .Parity = USART_Parity_No,
        .HardwareFlowControl = USART_HardwareFlowControl_None,
        .Mode = USART_Mode_Tx | USART_Mode_Rx,
        .TX_DMAx_Channely = DMA1_Channel6,
        .RX_DMAx_Channely = DMA1_Channel7,
        .USART_DMAReq = USART_DMAReq_Tx | USART_DMAReq_Rx,

        .USART_IT = USART_IT_IDLE,

        .NVIC_IRQChannel = USART2_IRQn,
        .NVIC_IRQChannelCmd = ENABLE,
        .NVIC_IRQChannelPreemptionPriority = 1,
        .NVIC_IRQChannelSubPriority = 1,

        .RCC_APB1Periph = RCC_APB1Periph_USART2,
        .RCC_APB2Periph = RCC_APB2Periph_GPIOA,
        .RCC_APB1PeriphClockCmd = RCC_APB1PeriphClockCmd,
        .RCC_APB2PeriphClockCmd = RCC_APB2PeriphClockCmd,

};

static Device_DMA_Typedef config_dma_tx = {
        .DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR),
        .DMA_MemoryBaseAddr = (u32)uart2_dma_tx_buffer,
        .DMA_DIR = DMA_DIR_PeripheralDST,
        .DMA_BufferSize = sizeof(uart2_dma_tx_buffer),
        .DMA_PeripheralInc = DMA_PeripheralInc_Disable,
        .DMA_MemoryInc = DMA_MemoryInc_Enable,
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
        .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
        .DMA_Mode = DMA_Mode_Normal,
        .DMA_Priority = DMA_Priority_Low,
        .DMA_M2M = DMA_M2M_Disable,

        .DMAx_Channely = DMA1_Channel7,

        .RCC_AHBPeriph = RCC_AHBPeriph_DMA1,
        .RCC_AHBPeriphClockCmd = RCC_AHBPeriphClockCmd,
        .DMAy_FLAG = DMA1_FLAG_TC7
};

static Device_DMA_Typedef config_dma_rx = {
        .DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR),
        .DMA_MemoryBaseAddr = (u32)uart2_dma_rx_buffer,
        .DMA_DIR = DMA_DIR_PeripheralSRC,
        .DMA_BufferSize = sizeof(uart2_dma_rx_buffer),
        .DMA_PeripheralInc = DMA_PeripheralInc_Disable,
        .DMA_MemoryInc = DMA_MemoryInc_Enable,
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
        .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
        .DMA_Mode = DMA_Mode_Normal,
        .DMA_Priority = DMA_Priority_Low,
        .DMA_M2M = DMA_M2M_Disable,

        .DMAx_Channely = DMA1_Channel6,

        .RCC_AHBPeriph = RCC_AHBPeriph_DMA1,
        .RCC_AHBPeriphClockCmd = RCC_AHBPeriphClockCmd,
};



/**
 * @brief 初始化CommunicationDevice类
 * @return none
 */
CommunicationDevice::CommunicationDevice() : CommDev(&config, &config_dma_tx, &config_dma_rx){
    memset(uart2_dma_rx_buffer, 0, DMA_RX_BUFFER_SIZE);  // 清空接收缓冲区
    memset(uart2_dma_tx_buffer, 0, DMA_TX_BUFFER_SIZE);  // 清空发送缓冲区

}


/**
 * @brief CommunicationDevice类析构函数
 * @return none
 */
CommunicationDevice::~CommunicationDevice() {

}


/**
 * @brief 串口通过DMA发送数据, UART2
 * @return none
 */
void CommunicationDevice::send_msg(void* msg, uint16_t len) {
    // ​​必须先等待上一次DMA传输完成，再关闭DMA通道​​
    while(DMA_GetFlagStatus(config_dma_tx.DMAy_FLAG) == RESET);
    DMA_Cmd(config_dma_tx.DMAx_Channely, DISABLE);

    len = (len > DMA_TX_BUFFER_SIZE) ? DMA_TX_BUFFER_SIZE : len;
    memcpy(uart2_dma_tx_buffer, msg, len);

    DMA_SetCurrDataCounter(config_dma_tx.DMAx_Channely, len);
    DMA_Cmd(config_dma_tx.DMAx_Channely, ENABLE);

//        // CH32上可以不要这个
//        // 使能USART的DMA传输请求
//        USART_DMACmd(config.UARTx, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
}


void CommunicationDevice::extract_json_simple(const char *input, char *output) {
    const char *start = strchr(input, '{'); // 查找第一个{

    if (start != NULL) {
        strcpy(output, start); // 复制从{开始的所有内容
    } else {
        output[0] = '\0'; // 没有找到{则返回空字符串
    }
}


/**
 * @brief 解析串口接受的数据
 * @return none
 */
void CommunicationDevice::CommunicationDev_Data_Perse() {
    DMA_Cmd(config_dma_rx.DMAx_Channely, DISABLE);

    uint16_t received_len = DMA_RX_BUFFER_SIZE - DMA_GetCurrDataCounter(config_dma_rx.DMAx_Channely);
    received_len = (received_len > DMA_RX_BUFFER_SIZE) ? DMA_RX_BUFFER_SIZE : received_len;

    CH32_LOGI(CommunicationDeviceTAG, "USART DMA RX (%d bytes)", received_len);

    static char temp_buf[DMA_RX_BUFFER_SIZE + 1] = {0};
    static char fixed_buf[DMA_RX_BUFFER_SIZE + 1] = {0};
    if (received_len > 0) {
        uint16_t copy_len = (received_len < DMA_RX_BUFFER_SIZE) ? received_len : DMA_RX_BUFFER_SIZE;

        memcpy(temp_buf, uart2_dma_rx_buffer, copy_len);
        temp_buf[copy_len] = '\0';
        CH32_LOGI(CommunicationDeviceTAG, "RX : %s", temp_buf);

        // CCLK时间戳处理
        if (strstr(temp_buf, "+CCLK:")) {
            char cclk[timestamp_buffer_size] = {0};

            strncpy(cclk, temp_buf, sizeof(cclk)-1);

            if (xQueueSend(Timestamp_msg_Queue, cclk, pdMS_TO_TICKS(10)) == pdTRUE) {
                CH32_LOGI(CommunicationDeviceTAG, "sending timestamp: %s to Timestamp_msg_Queue", cclk);
            }
            goto cleanup;
        }

        extract_json_simple(temp_buf, fixed_buf);
        if (fixed_buf[0] == '\0') {
            CH32_LOGW("CommunicationDev_Data_Perse", "No Json Msg");
            memset(fixed_buf, 0, DMA_RX_BUFFER_SIZE);
            goto cleanup;
        }

        // JSON解析
        cJSON *root = cJSON_Parse(temp_buf);
        if (root != NULL) {
            cJSON* cmd = cJSON_GetObjectItemCaseSensitive(root, "type");
            if (strcmp(cmd->valuestring, "update")) {
                cJSON* device_id = cJSON_GetObjectItemCaseSensitive(root, "device_id");
                OTA_Update_Cmd_Typedef update_cmd = {0};
                strcpy(update_cmd.type, cmd->valuestring);
                strcpy(update_cmd.device_id, device_id->valuestring);
                xQueueSend(OTA_Update_Cmd_Queue, &update_cmd, pdMS_TO_TICKS(10));
            }
            cJSON_Delete(root);
        }
    }

cleanup:
    memset(uart2_dma_rx_buffer, 0, DMA_RX_BUFFER_SIZE);
    memset(temp_buf, 0, DMA_RX_BUFFER_SIZE);
    memset(fixed_buf, 0, DMA_RX_BUFFER_SIZE);
    DMA_SetCurrDataCounter(config_dma_rx.DMAx_Channely, DMA_RX_BUFFER_SIZE);
    DMA_Cmd(config_dma_rx.DMAx_Channely, ENABLE);
}



/*
 * @brief UART2中断处理函数
 * 极致缩短中断任务内容，通过二进制信号量触发外部专门的线程来解析数据
 * @return none
 */
extern "C" void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
extern "C" void USART2_IRQHandler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    if (USART_GetITStatus(config.UARTx, config.USART_IT) != RESET)
    {
        xSemaphoreGiveFromISR(CommunicationDevice_xBinarySemaphore, &xHigherPriorityTaskWoken);

        volatile uint32_t temp;  // 读SR+DR清除空闲中断标志
        temp = config.UARTx->STATR;
        temp = config.UARTx->DATAR;
        (void)temp;
//          下面方法也一样的
//        USART_ReceiveData(config.UARTx);
//        USART_ClearFlag(config.UARTx, config.USART_IT);
    }
}







// uart3 情况
//
//
//char uart3_dma_rx_buffer[DMA_RX_BUFFER_SIZE];
//char uart3_dma_tx_buffer[DMA_TX_BUFFER_SIZE];
//
//
//
//static UART_Device_Typedef config = {
//        .UARTx = USART3,
//        .port = GPIOB,
//        .tx_pin = GPIO_Pin_10,
//        .rx_pin = GPIO_Pin_11,
//        .gpio_tx_pin_mode = GPIO_Mode_AF_PP,
//        .gpio_rx_pin_mode = GPIO_Mode_IN_FLOATING,
//
//        .BaudRate = 115200,
//        .WordLength = USART_WordLength_8b,
//        .StopBits = USART_StopBits_1,
//        .Parity = USART_Parity_No,
//        .HardwareFlowControl = USART_HardwareFlowControl_None,
//        .Mode = USART_Mode_Tx | USART_Mode_Rx,
//        .TX_DMAx_Channely = DMA1_Channel2,
//        .RX_DMAx_Channely = DMA1_Channel3,
//        .USART_DMAReq = USART_DMAReq_Tx | USART_DMAReq_Rx,
//
//        .USART_IT = USART_IT_IDLE,
//
//        .NVIC_IRQChannel = USART3_IRQn,
//        .NVIC_IRQChannelCmd = ENABLE,
//        .NVIC_IRQChannelPreemptionPriority = 1,
//        .NVIC_IRQChannelSubPriority = 1,
//
//        .RCC_APB1Periph = RCC_APB1Periph_USART3,
//        .RCC_APB2Periph = RCC_APB2Periph_GPIOB,
//        .RCC_APB1PeriphClockCmd = RCC_APB1PeriphClockCmd,
//        .RCC_APB2PeriphClockCmd = RCC_APB2PeriphClockCmd,
//
////        .Data_Send_Func = Dev1_DMA_Send
//};
//
//static Device_DMA_Typedef config_dma_tx = {
//        .DMA_PeripheralBaseAddr = (u32)(&USART3->DATAR),
//        .DMA_MemoryBaseAddr = (u32)uart3_dma_tx_buffer,
//        .DMA_DIR = DMA_DIR_PeripheralDST,
//        .DMA_BufferSize = sizeof(uart3_dma_tx_buffer),
//        .DMA_PeripheralInc = DMA_PeripheralInc_Disable,
//        .DMA_MemoryInc = DMA_MemoryInc_Enable,
//        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
//        .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
//        .DMA_Mode = DMA_Mode_Normal,
//        .DMA_Priority = DMA_Priority_Low,
//        .DMA_M2M = DMA_M2M_Disable,
//
//        .DMAx_Channely = DMA1_Channel2,
//
//        .RCC_AHBPeriph = RCC_AHBPeriph_DMA1,
//        .RCC_AHBPeriphClockCmd = RCC_AHBPeriphClockCmd,
//        .DMAy_FLAG = DMA1_FLAG_TC2
//};
//
//static Device_DMA_Typedef config_dma_rx = {
//        .DMA_PeripheralBaseAddr = (u32)(&USART3->DATAR),
//        .DMA_MemoryBaseAddr = (u32)uart3_dma_rx_buffer,
//        .DMA_DIR = DMA_DIR_PeripheralSRC,
//        .DMA_BufferSize = sizeof(uart3_dma_rx_buffer),
//        .DMA_PeripheralInc = DMA_PeripheralInc_Disable,
//        .DMA_MemoryInc = DMA_MemoryInc_Enable,
//        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
//        .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
//        .DMA_Mode = DMA_Mode_Normal,
//        .DMA_Priority = DMA_Priority_High,
//        .DMA_M2M = DMA_M2M_Disable,
//
//        .DMAx_Channely = DMA1_Channel3,
//
//        .RCC_AHBPeriph = RCC_AHBPeriph_DMA1,
//        .RCC_AHBPeriphClockCmd = RCC_AHBPeriphClockCmd,
//};
//
//
///**
// * @brief 初始化CommunicationDevice类
// * @return none
// */
//CommunicationDevice::CommunicationDevice() : CommDev(&config, &config_dma_tx, &config_dma_rx){
//    memset(uart3_dma_rx_buffer, 0, DMA_RX_BUFFER_SIZE);  // 清空接收缓冲区
//    memset(uart3_dma_tx_buffer, 0, DMA_TX_BUFFER_SIZE);  // 清空发送缓冲区
//
//}
//
//
///**
// * @brief CommunicationDevice类析构函数
// * @return none
// */
//CommunicationDevice::~CommunicationDevice() {
//
//}
//
///**
// * @brief 串口通过DMA发送数据, UART3
// * @return none
// */
//void CommunicationDevice::send_msg(void* msg, uint16_t len) {
//    // ​​必须先等待上一次DMA传输完成，再关闭DMA通道​​
//    while(DMA_GetFlagStatus(config_dma_tx.DMAy_FLAG) == RESET);
//    DMA_Cmd(config_dma_tx.DMAx_Channely, DISABLE);
//
//    CH32_LOGI(CommunicationDeviceTAG, "USART_DMA_is_Sending");
//
//    len = (len > DMA_TX_BUFFER_SIZE) ? DMA_TX_BUFFER_SIZE : len;
//    memcpy(uart3_dma_tx_buffer, msg, len);
//
//    DMA_SetCurrDataCounter(config_dma_tx.DMAx_Channely, len);
//    DMA_Cmd(config_dma_tx.DMAx_Channely, ENABLE);
//
////        // CH32上可以不要这个
////        // 使能USART的DMA传输请求
////        USART_DMACmd(config.UARTx, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
//}
//
//
//
//void CommunicationDev_Data_Perse() {
//    // 1. 获取接收数据长度
//    uint16_t received_len = DMA_RX_BUFFER_SIZE - DMA_GetCurrDataCounter(config_dma_rx.DMAx_Channely);
//
//    // 2. 安全限制长度（防止溢出）
//    received_len = (received_len > DMA_RX_BUFFER_SIZE) ? DMA_RX_BUFFER_SIZE : received_len;
//
//    CH32_LOGI(CommunicationDeviceTAG, "USART DMA RX (%d bytes)", received_len);
//
//    if(received_len > 0) {
//        // 3. 安全处理字符串
//        char temp_buf[DMA_RX_BUFFER_SIZE + 1] = {0};
//        uint16_t copy_len = (received_len < DMA_RX_BUFFER_SIZE) ? received_len : DMA_RX_BUFFER_SIZE;
//
//        memcpy(temp_buf, uart3_dma_rx_buffer, copy_len);
//        temp_buf[copy_len] = '\0'; // 添加终止
//
//        // 4. 检查是否可打印
//        bool is_printable = true;
//        for(uint16_t i = 0; i < copy_len; i++) {
//            if(!isprint(temp_buf[i]) && !isspace(temp_buf[i])) {
//                is_printable = false;
//                break;
//            }
//        }
//
//        if(is_printable) {
//            CH32_LOGI(CommunicationDeviceTAG, "RX String: %s", temp_buf);
//        } else {
//            // 16进制格式输出非文本数据
//            CH32_LOGI(CommunicationDeviceTAG, "RX Hex Data:");
//            for(uint16_t i = 0; i < copy_len; i++) {
//                printf("0x%02X ", (uint8_t)temp_buf[i]);
//            }
//            printf("\n");
//        }
//    }
//
//    // 5. 重置DMA前清空缓冲区
//    memset(uart3_dma_rx_buffer, 0, DMA_RX_BUFFER_SIZE);
//}
//
//
//// 必须添加extern "C"防止C++对中断命名影响
//extern "C" void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
//extern "C" void USART3_IRQHandler(void) {
//    if (USART_GetITStatus(config.UARTx, config.USART_IT) != RESET)
//    {
//        DMA_Cmd(config_dma_rx.DMAx_Channely, DISABLE);
//
//        CH32_LOGI(CommunicationDeviceTAG, "UART3 is RX");
//
//        DMA_SetCurrDataCounter(config_dma_rx.DMAx_Channely, DMA_RX_BUFFER_SIZE);
//        DMA_Cmd(config_dma_rx.DMAx_Channely, ENABLE);
//
//
//        volatile uint32_t temp;  // 读SR+DR清除空闲中断标志
//        temp = config.UARTx->STATR;
//        temp = config.UARTx->DATAR;
//        (void)temp;
////          下面方法也一样的
////        USART_ReceiveData(config.UARTx);
////        USART_ClearFlag(config.UARTx, config.USART_IT);
//    }
//}
